/*
Copyright (C) 2022-2024 Inspur Corp. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/
package controller

import (
	"did-service/bean/model"
	"did-service/bean/param"
	"did-service/common/constant"
	"did-service/common/http"
	"did-service/common/uuid"
	"did-service/config"

	"github.com/emicklei/go-restful"
)

func (dc *DidController) RegisterUserAndGetApiKey(req *restful.Request, resp *restful.Response) {
	var userParam param.RegisterUserParam
	if err := req.ReadEntity(&userParam); err != nil {
		log.Errorf("register user and get api key read entity error: %v", err)
		http.Failed(resp, "请求参数不合法！")
		return
	}

	if userParam.UserType != constant.UserTypePerson && userParam.UserType != constant.UserTypeIssuer &&
		userParam.UserType != constant.UserTypeEnterprise {
		log.Errorf("only person user, org user, enterprise user can be created!")
		http.Failed(resp, "请求参数不合法！")
		return
	}

	if userParam.Password == "" {
		log.Errorf("usertype or password empty!")
		http.Failed(resp, "请求参数不合法！")
		return
	}

	if userParam.UserName == "" {
		log.Errorf("username is empty!")
		http.Failed(resp, "请求参数不合法！")
		return
	}

	walletId, err := dc.srv.RegisterUser(userParam)
	if err != nil {
		log.Errorf("register user error: %s", err)
		http.Failed(resp, err.Error())
		return
	}

	_, err = dc.srv.CreateDid(walletId)
	if err != nil {
		log.Errorf("create did error: %v", err)
		http.Failed(resp, "用户创建成功，DID申请失败！")
		return
	}

	apiKey, err := dc.srv.CreateApiKey(walletId)
	if err != nil {
		log.Errorf("create api key error: %v", err)
		http.Failed(resp, "创建ApiKey失败")
		return
	}
	http.OkWithData(resp, "注册成功", apiKey)

}

func (dc *DidController) ApplyDidByApiKey(req *restful.Request, resp *restful.Response) {
	var p param.ApplyDidParam
	if err := req.ReadEntity(&p); err != nil {
		log.Errorf("apply did, read entity error: %v", err)
		http.Failed(resp, "请求参数不合法！")
		return
	}

	if p.ApiKey == "" {
		log.Errorf("apply did, api key is null")
		http.Failed(resp, "请求参数不合法！")
		return
	}

	if p.Signature == "" {
		log.Errorf("apply did, signature is null")
		http.Failed(resp, "请求参数不合法！")
		return
	}

	checkResult, walletId, err := dc.srv.CheckApi(p.ApiKey, p.Signature, p)
	if err != nil {
		log.Errorf("apply vc without did, check api error: %v", err)
		http.Failed(resp, "认证失败")
		return
	}
	if !checkResult {
		http.Failed(resp, "认证失败")
		return
	}

	document, err := dc.srv.CreateDid(walletId)
	if err != nil {
		log.Errorf("create did error: %v", err)
		http.Failed(resp, "DID申请失败！")
		return
	}

	keys, err := dc.srv.ListKeyByDid(document.Did)
	if err != nil {
		log.Errorf("get keys by did error: %v", err)
		http.Failed(resp, "获取失败")
		return
	}
	keyPairs := make([]model.KeyPair, 0)
	for _, d := range keys {
		keyPair := model.KeyPair{}
		keyPair.Id = d.KeyId
		keyPair.Type = constant.DefaultKeyAlgo
		keyPair.PublicKeyHex = d.PubKey
		keyPair.PrivateKeyHex = d.PrvKey
		keyPairs = append(keyPairs, keyPair)
	}

	services := make([]model.Service, 0)
	service := model.Service{}
	service.Id = document.Did + constant.DefaultServiceResolveSubfix
	service.Type = constant.DefaultServiceResolveType
	service.ServiceEndpoint = config.Get("did.endpoint", constant.DefaultServiceResolveEndpoint) + constant.DidResolveUrlSuffix
	services = append(services, service)

	proof := model.Proof{
		Type:           constant.DefaultKeyAlgo,
		Creator:        document.ProofCreator,
		SignatureValue: document.ProofSignature,
	}

	result := model.Document{
		Context:        constant.DefaultContext,
		Id:             document.Did,
		Version:        document.Version,
		Created:        document.CreatedTime.Format(constant.TimeLayout),
		Updated:        document.UpdatedTime.Format(constant.TimeLayout),
		KeyPairs:       keyPairs,
		Authentication: []string{document.AuthPubKey},
		Recovery:       []string{document.RecoveryPubKey},
		Service:        services,
		Proof:          proof,
	}
	http.OkWithData(resp, "申请成功", result)
}

func (dc *DidController) ApplyVcWithoutDid(req *restful.Request, resp *restful.Response) {
	var p param.ApplyVcWithoutDidParam

	if err := req.ReadEntity(&p); err != nil {
		log.Errorf("apply vc without did, read entity error: %v", err)
		http.Failed(resp, "请求参数不合法！")
		return
	}

	if p.ApiKey == "" {
		log.Errorf("apply vc without did, api key is null")
		http.Failed(resp, "请求参数不合法！")
		return
	}

	if p.Signature == "" {
		log.Errorf("apply vc without did, signature is null")
		http.Failed(resp, "请求参数不合法！")
		return
	}

	if p.IssuerId == "" {
		log.Errorf("apply vc without did, issuer id is null")
		http.Failed(resp, "请求参数不合法！")
		return
	}

	if p.CptId == "" {
		log.Errorf("apply vc without did, cpt id is null")
		http.Failed(resp, "请求参数不合法！")
		return
	}

	if p.Claims == "" {
		log.Errorf("apply vc without did, Claims is null")
		http.Failed(resp, "请求参数不合法！")
		return
	}

	checkResult, _, err := dc.srv.CheckApi(p.ApiKey, p.Signature, p)
	if err != nil {
		log.Errorf("apply vc without did, check api error: %v", err)
		http.Failed(resp, "认证失败")
		return
	}
	if !checkResult {
		http.Failed(resp, "认证失败")
		return
	}

	result, err := dc.srv.ApplyVcWithoutDid(&p)
	if err != nil {
		log.Errorf("apply vc without did error: %v", err)
		http.Failed(resp, "申请失败")
		return
	}

	http.OkWithData(resp, "申请成功", result)
}

func (dc *DidController) ApplyVpByApiKey(req *restful.Request, resp *restful.Response) {
	var p param.ApplyVpByApiKeyParam
	if err := req.ReadEntity(&p); err != nil {
		log.Errorf("apply vp by api key, read entity error: %v", err)
		http.Failed(resp, "请求参数不合法！")
		return
	}
	if p.ApiKey == "" {
		log.Errorf("apply vc without did, api key is null")
		http.Failed(resp, "请求参数不合法！")
		return
	}

	if p.Signature == "" {
		log.Errorf("apply vc without did, signature is null")
		http.Failed(resp, "请求参数不合法！")
		return
	}

	checkResult, walletId, err := dc.srv.CheckApi(p.ApiKey, p.Signature, p)
	if err != nil {
		log.Errorf("apply vp by api key, check api error: %v", err)
		http.Failed(resp, "认证失败")
		return
	}
	if !checkResult {
		http.Failed(resp, "认证失败")
		return
	}

	//校验凭证
	ok, info, credDetail, err := dc.srv.ValidateCredential(walletId, p.VcId)
	if err != nil {
		log.Errorf("error: %v", err)
		http.Failed(resp, "验证凭证失败!")
		return
	}
	if !ok {
		http.Failed(resp, info)
		return
	}

	vpId := uuid.Generate()
	//生成可验证凭证
	if err = dc.srv.GeneratePresentation(walletId, vpId, credDetail.Credential, &param.ApplyPresentationParam{
		Name:           p.Name,
		CredId:         p.VcId,
		AdditionalInfo: p.AdditionalInfo,
		Challenge:      "",
		Domain:         constant.DefaultVpDomain,
	}); err != nil {
		log.Errorf("err: %v", err)
		http.Failed(resp, "生成VP失败!")
		return
	}

	detail, err := dc.srv.QueryPresentationDetail(walletId, vpId)
	if err != nil {
		log.Errorf("err: %v", err)
		http.Failed(resp, "获取VP失败!")
		return
	}
	http.OkWithData(resp, "", model.ApplyVpByApiKeyResult{
		VpId: vpId,
		Vp:   detail.Presentation,
	})
}
